#include "timer.h"


#undef TRACE_LEVEL
#undef TRACE_TITLE
#undef TRACE_TITLE
#define TRACE_LEVEL	TRACE_LEVEL_DEBUG
#define TRACE_NAME  TRACE_NAME_DISABLE
#define TRACE_TITLE "TIM"
#include "trace.h"


static TIM_TypeDef *TIMER = TIM4;

static unsigned int ADD_PER_131MS = 0;

/* 2uS per tick */
#define PRESCALER	(uint16_t)(72000000 / 500000 - 1);

/*
** @ Init System 2us tick
**/
void Sys_2usTick_Init(void) {
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	
	TIM_DeInit(TIMER);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
	TIM_TimeBaseStructure.TIM_Period=65535;
	TIM_TimeBaseStructure.TIM_Prescaler=PRESCALER;
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIMER, &TIM_TimeBaseStructure);
	TIM_ITConfig(TIMER,TIM_IT_Update,ENABLE);
	TIM_Cmd(TIMER, ENABLE);
}

/*
** @ Stop System 2us tick
**/
void Sys_2usTick_Deinit(void) {
	TIM_ITConfig(TIMER,TIM_IT_Update, DISABLE);
	TIM_DeInit(TIMER);
}

/*
** @ Read System 2us tick
**/
void GetSys2usTick(uint32_t *high, uint16_t *low) {
	*high = ADD_PER_131MS << 16;
	*low = 65535 - TIMER->CNT;
}

/*
** @ Timer Delay 2*n us
**/
void delay_us(uint32_t us) {
	uint32_t mark = TIMER->CNT;
	
	mark += (us >> 1);
	if(mark > 0xFFFF) {
		mark &= 0xFFFF;
		while (TIMER->CNT > mark);		
	} 
	while ( mark > TIMER->CNT );
}

/*
** @ Timer Interrupt Callback
**/
void Timer_Callback(void) {
	ADD_PER_131MS ++;
}


// TEST ONLY ****** TEST ONLY ****** TEST ONLY ****** TEST ONLY ****** TEST ONLY ******
int TIMER_Main() {
	int i;
	
	while (1) {
		TRACE_DEBUG("%d", i ++);
		delay_us(1000000);
	}
}
